home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / misc / volume27 / psf3 / part09 < prev    next >
Encoding:
Text File  |  1992-01-20  |  55.0 KB  |  2,073 lines

  1. Newsgroups: comp.sources.misc
  2. From: tony@ajfcal.cuc.ab.ca (Tony Field)
  3. Subject:  v27i100:  psf3 - Postscript print filter system, v3, Part09/09
  4. Message-ID: <1992Jan21.013608.11883@sparky.imd.sterling.com>
  5. X-Md4-Signature: 26baf202402123037516542481bcd20b
  6. Date: Tue, 21 Jan 1992 01:36:08 GMT
  7. Approved: kent@sparky.imd.sterling.com
  8.  
  9. Submitted-by: tony@ajfcal.cuc.ab.ca (Tony Field)
  10. Posting-number: Volume 27, Issue 100
  11. Archive-name: psf3/part09
  12. Environment: ISC, SUNOS, SYSVR3, DOS
  13. Supersedes: psf2: Volume 12, Issue 4-9
  14.  
  15. #! /bin/sh
  16. # This is a shell archive.  Remove anything before this line, then unpack
  17. # it by saving it into a file and typing "sh file".  To overwrite existing
  18. # files, type "sh file -c".  You can also feed this as standard input via
  19. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  20. # will see the following message at the end:
  21. #        "End of archive 9 (of 9)."
  22. # Contents:  psf.c
  23. # Wrapped by ajf@trifid on Sat Jan 18 22:55:51 1992
  24. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  25. if test -f 'psf.c' -a "${1}" != "-c" ; then 
  26.   echo shar: Will not clobber existing file \"'psf.c'\"
  27. else
  28. echo shar: Extracting \"'psf.c'\" \(52453 characters\)
  29. sed "s/^X//" >'psf.c' <<'END_OF_FILE'
  30. X/* ta=4        set tabstop=4    */
  31. X/****************************************************************************
  32. X*                     p s f . c        v3                                        *
  33. X*                                                                            *
  34. X*    Print text files to postscript printer.                                    *
  35. X*                                                                            *
  36. X*    Tony Field: tony@ajfcal.cuc.ab.ca                                        *
  37. X****************************************************************************/
  38. X/*
  39. X * $Id: psf.c,v 3.2 1992/01/19 05:50:33 ajf Exp ajf $
  40. X*/
  41. X/*    Three versions of psf can be compiled:
  42. X
  43. X        psf:        postscript filter for command line use.
  44. X            
  45. X        psffilter:    used with lp/lpsched.  accepts command line argument.
  46. X                    Input on stdin. compile with -DPSFFILTER.
  47. X
  48. X        psflpd:        used with lpr/lpd.  does not accept command line
  49. X                    arguments.  compile with -DPSFFILTER -DFORLPD
  50. X */
  51. X
  52. X#include <stdio.h>
  53. X#include <malloc.h>
  54. X#include <string.h>
  55. X#include <setjmp.h>
  56. X#include <math.h>
  57. X#include <time.h>
  58. X#include <signal.h>
  59. X#include "ctp.h"
  60. X#include "patchlevel.h"
  61. X#include "psf.h"
  62. X#include "psfproto.h"
  63. X
  64. X#if defined(MSDOS)  ||  defined (__MSDOS__)
  65. X#ifndef BINDIR
  66. X#define BINDIR "c:/bin"
  67. X#endif
  68. X#ifndef PDEF
  69. X#define PDEF "c:/lib/psfprint.def"
  70. X#endif
  71. X#endif
  72. X
  73. X#ifndef PAPERTYPE
  74. X#define PAPERTYPE "letter"
  75. X#endif
  76. X#ifndef PSFDOUB
  77. X#define PSFDOUB "psfdoub"
  78. X#endif
  79. X
  80. X/*    set up the mechanism for underline display */
  81. X
  82. X#define SHOWU(fp,ps)    fprintf (fp, ") %d showuline\n", ps)
  83. X
  84. X#define NOMINAL_CWIDE    7.2001    /* point width for Courier 12-point            */
  85. X#define NOMINAL_POINTS    12        /* standard 12-point for printing            */
  86. X
  87. X#define NORMAL        0x00        /* bitset for  print_attributes                */
  88. X#define ITALICS        0x01
  89. X#define BOLD        0x02
  90. X#define UNDERLINE    0x04        /* must be 0x04.  underline is not a font    */
  91. X
  92. X#define CTLD_EOJ    0x04        /* ctl/d is end of postscript job.            */
  93. X
  94. X/*    Paper physical dimensions.
  95. X    The default paper sizes is for a NEC LC890 and is overridden in
  96. X    "psfprint.def".
  97. X*/
  98. X
  99. Xtypedef struct                     /*    measurement in point                    */
  100. X{    char    paper_name[60];        /*    name of paper size (for command line)    */
  101. X    char    paper_tray[100];    /*    postscript operator to select this tray    */
  102. X    int        width;                /*    portrait point width of paper            */
  103. X    int        height;                /*    portrait point height of paper            */
  104. X    int        lx, ly, ux, uy;
  105. X    int        left_marg;            /*    margin widths (unprintable area)        */
  106. X    int        bot_marg;            /*            "                                */
  107. X    int        right_marg;            /*            "                                */
  108. X    int        top_marg;            /*            "                                */
  109. X    int        x_size;                /*    generated by psf.                        */
  110. X    int        y_size;                /*    size after correction for line count    */
  111. X} measure;
  112. X
  113. Xmeasure    *p;        /*    working set of parameters  (points to something below)     */
  114. Xmeasure    page_types[NPAGE] =
  115. X{            {     "letter",
  116. X                "statusdict begin lettertray end",
  117. X                  612,   792,    18,    15,   593,   777
  118. X            },
  119. X            {     "legal",
  120. X                "statusdict begin legaltray end",
  121. X                  612,  1008,    18,    15,   593,   993
  122. X            },
  123. X            {    "a4",
  124. X                "statusdict begin a4tray end",
  125. X                  595,   842,    18,    15,   578,   827
  126. X            },
  127. X            {    "b5",
  128. X                "statusdict begin b5tray end",
  129. X                  516,   729,    18,    15,   497,   712
  130. X            },
  131. X            {    "",            /* end of paper list */
  132. X                "",
  133. X                 0, 0,  0,  0, 0, 0, 0, 0, 0, 0 
  134. X            }
  135. X};
  136. X
  137. Xchar    order_default[20] = "Normal";
  138. Xchar    order_normal[100] = "\0";
  139. Xchar    order_reverse[100] = "\0";
  140. Xchar    *order_command = NULL;
  141. X
  142. Xchar    slots[NSLOTS][200] = 
  143. X{            "statusdict begin 1 setpapertray end",
  144. X            "statusdict begin 2 setpapertray end",
  145. X            "", "", "", ""
  146. X} ;
  147. Xint        nslots = 2;
  148. X
  149. Xint        y_top_offset;            /*    offsets for each frame                    */
  150. Xint        x_left_offset;
  151. Xint        dx_home[4];                /*    page frame home (0,0) translations        */
  152. Xint        dy_home[4];
  153. X
  154. Xint        x,y;                    /* current x,y coordinate                    */
  155. Xdouble    scale_x, scale_y;        /* scale factors for 2-up, 4-up printing    */
  156. Xint        real_width;
  157. X
  158. Xlong    *pg_loc;                /* double side print byte ptr to %%Page:    */
  159. Xint        npg_loc;                /* number of elements in pg_loc[]            */
  160. X
  161. Xint        book             = 0;    /* book format: double sided                */
  162. Xint        bookwork        = 0;    /* book format, 2-up print                    */
  163. Xint        lines_on_page     = 60;    /* user print lines on page                    */
  164. Xint        lines_total     = 0;    /* total number of lines for scale purposes    */
  165. Xint        chars_on_line     = 80;    /* default number of chars on line            */
  166. Xint        landscape         = 0;    /* 1 = landscape, 0 = portrait layout        */
  167. Xint        header            = 0;    /* 1 = print header at top of each page        */
  168. Xint        cross              = 0;    /* 1 = print cross on 4-up pages            */
  169. Xint        line_number        = 0;    /* current logical line number on page        */
  170. Xint        tab_size           = 8;    /* space translation for tabs.                */
  171. Xint        font_number     = 0;    /* one of the valid fonts in the printer    */
  172. Xint        point_size        = 12;    /* can be changed with the -p option        */
  173. Xint        x_user_offset     = 0;    /* offsets specified buy user                */
  174. Xint        y_user_offset     = 0;    /* points from physical page edge.            */
  175. Xint        set_paper_tray     = 0;    /* user has set paper tray selection        */
  176. Xint        set_line_count     = 0;    /*                print line count on page    */
  177. Xint        set_total_count    = 0;    /*                total line count on page    */
  178. Xint        set_point_size     = 0;    /*                point size                    */
  179. Xint        set_char_count     = 0;    /*                characters on a line        */
  180. Xint        set_paper_bin    = 0;    /*                paper bin (not page size)    */
  181. Xchar    header_text[100];        /*                header line text            */
  182. X
  183. Xint        print_attribute = 0;    /* such as BOLD, UNDERLINE, ITALICS            */
  184. Xint        default_font_number;    /* set with -f option, or 0                    */
  185. Xint        default_point_size;        /* assumes value due to -p option            */
  186. Xint        y_coord            = 0;    /* current logical page y-coordinate, points*/
  187. Xint        x_coord            = 0;    /* current logical page x-coordinate, points*/
  188. Xint        page_number;            /* current page number for this file        */
  189. Xint        physical_page     = 0;    /* postscript physical page for multi-up    */
  190. Xint        print_postscript = 0;     /* force print of postscript                */
  191. Xint        remove_beginning = 0;    /* remove lines at beginning of job            */
  192. Xint        remove_between    = 0;    /* remove lines between printed pages        */
  193. Xint        is_a_formfeed    = 0;    /* skip to top of page caused by formfeed    */
  194. Xint        end_of_file        = 0;    /* end of printing file                        */
  195. Xint        save_point_size ;        /* save original point size for headers        */
  196. Xint        n_chars;                /*    number of characters on a line            */
  197. Xint        reverse_order    = 0;    /*     print in reverse_order                    */
  198. Xint        reverse_requested = 0;    /*    user option for reverse order            */
  199. Xchar    fname[100];
  200. Xchar    now[50];                /* time of day for page headers             */
  201. X
  202. X#ifdef HOPPER
  203. Xint        hopper_available = 1;
  204. X#else
  205. Xint        hopper_available = 0;
  206. X#endif
  207. X
  208. X/*    to select a font, use 4 * font_number + print_attribute as index.
  209. X
  210. X    Helvetica-Bold = fonts[4 * 1 + 2]
  211. X                   = fonts [4 * 1 + ITALICS | BOLD]
  212. X
  213. X    If one of the following fonts is found in "psfprint.def", then it is
  214. X    flagged as "available" (fonts_have[i] = 1), if not, it is
  215. X    "unavailable". This font list should include all known adobe fonts.
  216. X*/
  217. X      
  218. X#define NFONTS      144        /*     4 variations * 36 font families  */
  219. X
  220. Xint    font_count = 48;        /*    4 * 12 default fonts for fonts below    */
  221. Xchar *fonts[NFONTS] =
  222. X{
  223. X    /* base font                italics font                bold font                   bold-italics   */
  224. X
  225. X    "Courier",                    "Courier-Oblique",            "Courier-Bold",             "Courier-BoldOblique",
  226. X    "Helvetica",                 "Helvetica-Oblique",         "Helvetica-Bold",            "Helvetica-BoldOblique",
  227. X    "Times-Roman",                 "Times-Italic",             "Times-Bold",                 "Times-BoldItalic",
  228. X    "AvantGarde-Book",          "AvantGarde-BookOblique",   "AvantGarde-Demi",          "AvantGarde-DemiOblique",
  229. X    "Bookman-Light",            "Bookman-LightItalic",      "Bookman-Demi",             "Bookman-DemiItalic",
  230. X    "NewCenturySchlbk-Roman",   "NewCenturySchlbk-Italic",  "NewCenturySchlbk-Bold",    "NewCenturySchlbk-BoldItalic",
  231. X    "Palatino-Roman",           "Palatino-Italic",          "Palatino-Bold",            "Palatino-BoldItalic",
  232. X    "Helvetica-Narrow",         "Helvetica-Narrow-Oblique", "Helvetica-Narrow-Bold",    "Helvetica-Narrow-BoldOblique",
  233. X    "Garamond-Light",            "Garamond-LightItalic",        "Garamond-Bold",            "Garamond-BoldItalic",
  234. X    "Korinna-Regular",            "Korinna-KursivRegular",    "Korinna-Bold",                "Korinna-KursivBold",
  235. X    "Helvetica-Condensed",        "Helvetica-Condensed-Oblique", "Helvetica-Condensed-Bold", "Helvetica-Condensed-BoldObl",
  236. X    "ZapfChancery-MediumItalic","ZapfChancery-MediumItalic","ZapfChancery-MediumItalic","ZapfChancery-MediumItalic"
  237. X} ;
  238. X
  239. Xint    fonts_used[NFONTS];
  240. Xint    fonts_have[NFONTS];
  241. Xunsigned char    xlate[256];            /*    translation vector     */
  242. Xint        need_xlate = 0;                /*    no default xlate    */
  243. Xchar    copyfile[150];                /*    copy file name from psfprint.def */
  244. X
  245. Xint    max_frame    = 1;        /* max number of frames in use */
  246. Xint    frame        = -1;        /* current frame in use */
  247. X
  248. XFILE    *input_fp, *output_fp;
  249. X
  250. X/*    input line and input line pointer */
  251. Xchar    *c;
  252. Xchar    line[LONG_STR + 1];
  253. X
  254. Xchar    *pgmname;
  255. X
  256. Xvoid catch();
  257. Xjmp_buf eof_env;
  258. X
  259. Xchar    *defref = NULL;
  260. XFILE    *pdef = NULL;        /*    psfprint.def file    */
  261. X
  262. Xchar *ascii_hex = "0123456789abcdefghijklmnopqrstuvwxyz";
  263. Xextern int atoi(), getpid();
  264. X
  265. X/****************************************************************************
  266. X*    main ()                                                                    *
  267. X****************************************************************************/
  268. X
  269. Xmain (argc, argv)
  270. Xint        argc;
  271. Xchar    *argv[];
  272. X{    int        c, i, j, number;
  273. X    extern char *optarg;
  274. X    extern int    optind, getopt();
  275. X    char    bookfile[100];
  276. X    char    *env_fname;            /*    environment specified output file */
  277. X    char    *getenv();
  278. X    int        narrow2x;
  279. X    char    alt_cmd[200];
  280. X
  281. X    if ((pgmname = strrchr (argv[0], '/'))
  282. X            || (pgmname = strrchr (argv[0], '\\'))
  283. X            || (pgmname = strrchr (argv[0], ':')))
  284. X        pgmname++;
  285. X    else
  286. X        pgmname = argv[0];
  287. X
  288. X    copyfile[0] = 0;
  289. X    for (i = 0; i < 256;  i++)            /*    initial xlate = no translation */
  290. X        xlate[i] = i;
  291. X    for (i = font_count;  i < NFONTS;  i++)
  292. X        fonts[i] = "N/A";
  293. X
  294. X    for (i = 0;  i < argc;  i++)        /*    if user sets -u alt.def */
  295. X    {    if (strncmp (argv[i], "-u", 2) == 0)
  296. X        {    if (strlen (argv[i]) > 2)
  297. X                defref = argv[i] + 2;
  298. X         else
  299. X                defref = argv[i+1];
  300. X            break;
  301. X        }
  302. X    }
  303. X    if (i >= argc)
  304. X    {    if ((defref = getenv ("PSFDEF")) == NULL)
  305. X            defref = PDEF;
  306. X    }
  307. X
  308. X    /*    Read the .def file if it exists    */
  309. X
  310. X    alt_cmd[0] = '\0';
  311. X    if ((pdef = fopen (defref, "r")) != NULL)
  312. X    {    char    line_type[50];
  313. X#if defined(FORLPD)
  314. X        char    *quote, *word;
  315. X        int        modified_argv = 0;
  316. X
  317. X        /*    read lpd options from psfprint.def.  Format is:
  318. X                *psflpd argv0name opt1 opt2 opt3...
  319. X        */            
  320. X        while (fgets (alt_cmd, 200, pdef))
  321. X        {    if (*alt_cmd == '#')
  322. X                continue;
  323. X            alt_cmd[199] = '\0';
  324. X            trim (alt_cmd);
  325. X            word = strtok (alt_cmd, " \t");
  326. X            if (strcmp (word, "*psflpd") == 0)
  327. X            {    word = strtok (NULL, " \t");
  328. X                if (strcmp (word, pgmname) == 0)
  329. X                {    argv = (char **) malloc (sizeof (char *) * 50);
  330. X                    argv[0] = word;
  331. X                    modified_argv = 1;
  332. X                    for (argc = 1;  word = strtok (NULL, " \t");  argc++)
  333. X                    {    if (*word == '#')    /* quite on comments */
  334. X                            break;
  335. X                        argv[argc] = word;
  336. X                    }
  337. X                    argv[argc] = NULL;
  338. X                    break;
  339. X                }
  340. X            }
  341. X            else if (strcmp (word, "*printer") == 0)
  342. X                break;
  343. X        }
  344. X        if (modified_argv == 0)
  345. X        {    argc = 1;
  346. X            argv[1] = NULL;
  347. X        }
  348. X
  349. X#endif    /* FORLPD */
  350. X
  351. X        /*    skip to printer definition */
  352. X        if (strncmp (alt_cmd, "*printer", 8))
  353. X        {    while (fgets (line, 200, pdef))
  354. X            {    if (strncmp (line, "*printer", 8) == 0)
  355. X                    break;
  356. X            }
  357. X        }
  358. X        nslots = 0;
  359. X        fgets (line, 200, pdef);        /*    skip printer name     */
  360. X        while (fgets (line, 200, pdef))
  361. X        {    trim (line);
  362. X            sscanf (line, "%s%d", line_type, &number);
  363. X
  364. X            if (strcmp (line_type, "*paper") == 0)
  365. X            {    for (i = j = 0;  i < number;  i++)
  366. X                {    if (i >= NPAGE - 1)
  367. X                    {    fgets (line, 200, pdef);
  368. X                        fgets (line, 200, pdef);
  369. X                        fgets (line, 200, pdef);
  370. X                        continue;
  371. X                    }
  372. X                    if (fgets (line, 200, pdef) == NULL)
  373. X                        bad_file();
  374. X                    line[59] = 0;
  375. X                    trim (line);
  376. X                    strcpy (page_types[i].paper_name, line);
  377. X                    if (fgets (line, 99, pdef) == NULL)
  378. X                        bad_file();
  379. X                    line[99] = 0;
  380. X                    trim (line);
  381. X                    strcpy (page_types[i].paper_tray, line);
  382. X                    if (fgets (line, 100, pdef) == NULL)
  383. X                        bad_file();
  384. X                    trim (line);
  385. X                    sscanf (line, "%d%d%d%d%d%d",
  386. X                        &page_types[i].width, &page_types[i].height,
  387. X                        &page_types[i].lx,    &page_types[i].ly,
  388. X                        &page_types[i].ux,    &page_types[i].uy);
  389. X                    j = i;
  390. X                }
  391. X                page_types[j+1].paper_name[0] = '\0';
  392. X            }
  393. X                
  394. X            else if (strcmp (line_type, "*order") == 0)
  395. X            {    fgets (line, 200, pdef);
  396. X                line[19] = 0;
  397. X                trim (line);
  398. X                strcpy (order_default, line);
  399. X                if (number > 1)
  400. X                {    if (fgets (line, 200, pdef) == NULL)
  401. X                        bad_file();
  402. X                    trim (line);
  403. X                    line[99] = 0;
  404. X                    strcpy (order_normal, line);
  405. X                    if (fgets (line, 200, pdef) == NULL)
  406. X                        bad_file();
  407. X                    trim (line);
  408. X                    line[99] = 0;
  409. X                    strcpy (order_reverse, line);
  410. X                }
  411. X            }
  412. X            
  413. X            else if (strcmp (line_type, "*fonts") == 0)
  414. X            {    for (i = 0;  i < NFONTS;  i++)
  415. X                    fonts_have[i] = 0;
  416. X                for (i = 0;  i < number;  i++)
  417. X                {    if (fgets (line, 200, pdef) == NULL)
  418. X                        bad_file();
  419. X                    trim (line);
  420. X                    for (j = 0;  j < font_count;  j++)
  421. X                    {    if (compare (fonts[j], line) == 0)
  422. X                        {    fonts_have[j] = 1;
  423. X                            break;
  424. X                        }
  425. X                    }
  426. X                }
  427. X            }
  428. X
  429. X            else if (strcmp (line_type, "*slots") == 0)
  430. X            {    for (j = 0;  j < NSLOTS;  j++)
  431. X                    slots[j][0] = 0;
  432. X                for (i = j = 0;  i < number;  i++)
  433. X                {    if (fgets (line, 200, pdef) == NULL)
  434. X                        bad_file();
  435. X                    if (i >= NSLOTS)
  436. X                        continue;
  437. X                    line[99] = 0;
  438. X                    trim (line);
  439. X                    strcpy (slots[i], line);
  440. X                    j = i;
  441. X                }
  442. X                nslots = j + 1;
  443. X            }
  444. X
  445. X            else if (strcmp (line_type, "*eof") == 0)
  446. X                break;
  447. X            else
  448. X                bad_file();
  449. X        }
  450. X        replacement_fonts ();
  451. X    }
  452. X    else /* if no .def, assume all fonts exist */
  453. X    {    for (i = 0;  i < font_count;  i++)
  454. X            fonts_have[i] = 1;
  455. X    }
  456. X
  457. X    for (i = 0;  page_types[i].paper_name[0];  i++)
  458. X    {    page_types[i].left_marg  = page_types[i].lx;
  459. X        page_types[i].bot_marg   = page_types[i].ly;
  460. X        page_types[i].top_marg   = (page_types[i].height - 1) - page_types[i].uy;
  461. X        page_types[i].right_marg = (page_types[i].width  - 1) - page_types[i].ux;
  462. X
  463. X        page_types[i].x_size = page_types[i].ux - page_types[i].lx + 1;
  464. X        page_types[i].y_size = page_types[i].uy - page_types[i].ly + 1;
  465. X    }
  466. X        
  467. X#ifdef PAPERTYPE
  468. X    for (i = 0;  page_types[i].paper_name[0];  i++)
  469. X    {    if (strcmp (page_types[i].paper_name, PAPERTYPE) == 0)
  470. X        {    p = &page_types[i];
  471. X            break;
  472. X        }
  473. X    }
  474. X    if (page_types[i].paper_name[0] == '\0')
  475. X        p = &page_types[0];
  476. X#else
  477. X    p = &page_types[0];            /* default to letter size paper    */
  478. X#endif    /* PAPERTYPE */
  479. X
  480. X    *header_text = '\0';
  481. X    if (argc > 1  &&  (strcmp (argv[1], "-") == 0  || strcmp (argv[1], "--") == 0))
  482. X        usage();
  483. X
  484. X    narrow2x = 0;
  485. X    while ((c = getopt(argc, argv, "124xhnwdvzsi:m:b:c:g:H:l:L:f:t:p:r:R:u:-?")) != -1)
  486. X    {    switch (c)
  487. X        {
  488. X        case '1':
  489. X            max_frame = 1;
  490. X            break;
  491. X            
  492. X        case '2':
  493. X            if (narrow2x == 0)
  494. X                landscape = 1;
  495. X            max_frame = 2;
  496. X            break;
  497. X        
  498. X        case '4':
  499. X            max_frame = 4;
  500. X            break;
  501. X            
  502. X        case 'b':
  503. X            if ((set_paper_bin = atoi (optarg)) > nslots)
  504. X            {    if (nslots = 0)
  505. X                    fprintf (stderr, "%s: no alternate bins permitted\n", nslots);
  506. X                else
  507. X                    fprintf (stderr, "%s: paper bin greater than %d\n", pgmname, nslots);
  508. X                exit (1);
  509. X            }
  510. X            break;
  511. X
  512. X        case 'c':
  513. X            chars_on_line = atoi (optarg);
  514. X            set_char_count = 1;
  515. X            break;
  516. X
  517. X        case 'd':
  518. X            book = 1;
  519. X            break;
  520. X                    
  521. X        case 'f':
  522. X            if (*optarg > '9'  &&  optarg[1])        /*    at least 2 chars */
  523. X            {    /*    character string name of font */
  524. X                for (i = 0;  i < font_count;  i += 4)
  525. X                {    if (partial_compare (optarg, fonts[i]) == 0)
  526. X                    {    font_number =  i / 4;
  527. X                        break;
  528. X                    }
  529. X                }
  530. X                if (i >= font_count)
  531. X                    font_number = 0;
  532. X            }
  533. X            else
  534. X            {    /*    single digit hex */
  535. X                font_number = xtoi ((int) *optarg);
  536. X                if (font_number > (font_count / 4))
  537. X                    font_number = 0;
  538. X            }
  539. X            break;
  540. X
  541. X        case 'g':
  542. X            p = NULL;
  543. X            for (i = 0;  page_types[i].paper_name[0];  i++)
  544. X            {    if (compare (optarg, page_types[i].paper_name) == 0)
  545. X                {    p = &page_types[i];
  546. X                    break;
  547. X                }
  548. X            }
  549. X            if (p == NULL)
  550. X                usage ();
  551. X            set_paper_tray = 1;
  552. X            break;
  553. X
  554. X        case 'h':
  555. X            header = 1;
  556. X            break;
  557. X
  558. X        case 'H':
  559. X            header = 2;
  560. X            strcpy (header_text, optarg);
  561. X            break;
  562. X
  563. X        case 'i':
  564. X            x_user_offset = atoi (optarg);
  565. X            break;
  566. X
  567. X        case 'l':
  568. X            lines_on_page = atoi (optarg);
  569. X            set_line_count = 1;
  570. X            break;
  571. X
  572. X        case 'L':
  573. X            lines_total = atoi (optarg);
  574. X            set_total_count = 1;
  575. X            break;
  576. X
  577. X        case 'm':
  578. X            y_user_offset = atoi (optarg);
  579. X            break;
  580. X
  581. X        case 'n':
  582. X            landscape = 0;
  583. X            narrow2x = 1;
  584. X            break;
  585. X
  586. X        case 'p':
  587. X            point_size = atoi (optarg);
  588. X            set_point_size = 1;
  589. X            break;
  590. X
  591. X        case 'r':
  592. X            remove_between = atoi (optarg);
  593. X            break;
  594. X        
  595. X        case 'R':
  596. X            remove_beginning = atoi (optarg);
  597. X            break;
  598. X            
  599. X        case 's':
  600. X            size_display();
  601. X            exit (1);
  602. X    
  603. X        case 't':
  604. X            tab_size = atoi (optarg);
  605. X            break;
  606. X            
  607. X        case 'u':        /* already processed */
  608. X            break;
  609. X
  610. X        case 'v':
  611. X            reverse_requested = 1;
  612. X            break;
  613. X
  614. X        case 'w':
  615. X            landscape = 1;
  616. X            break;
  617. X            
  618. X        case 'x':
  619. X            cross = 1;
  620. X            break;
  621. X
  622. X        case 'z':
  623. X            print_postscript = 1;
  624. X            break;
  625. X
  626. X        default:    usage ();
  627. X            break;
  628. X        }
  629. X    }
  630. X
  631. X    if (strncmp (order_default, "Reverse", 7) == 0)        /*    stacking sequence         */
  632. X        reverse_order = 1;                                /*    "Reverse"                */
  633. X    else
  634. X        reverse_order = 0;                                /*    "Normal"                */
  635. X    if (reverse_requested)                                /*    User wants reverse ?    */
  636. X        reverse_order = !reverse_order;                    /*        yes                    */
  637. X    if (reverse_order  &&  order_reverse[0])            /*    Reverse tray command     */
  638. X    {    order_command = order_reverse;                    /*        yes                    */
  639. X        reverse_order = 0;                                /*        order_command does the work*/
  640. X    }
  641. X    else if (reverse_order == 0  &&  order_normal[0])    /*    Force normal order tray?*/
  642. X        order_command = order_normal;                    /*        yes                    */
  643. X    else
  644. X        order_command = NULL;                            /*    use default action         */
  645. X
  646. X    if (reverse_requested && book)
  647. X    {    fprintf (stderr, "Double sided or book in reverse ordered not supported\n");
  648. X        exit (1);
  649. X    }
  650. X
  651. X
  652. X    if (nslots <= 1)
  653. X        hopper_available = 0;
  654. X    if (reverse_order  ||  (book  &&  hopper_available))
  655. X        sprintf (bookfile, "%s%d.bok", TEMPFILE, getpid());
  656. X    else
  657. X        strcpy (bookfile, BOOKFILE);
  658. X
  659. X    if (max_frame == 2  &&  landscape == 0)
  660. X        set_point_size = 1;
  661. X    if (optind >=  argc  &&  header == 1)    /* no file name header on stdin */
  662. X        header = 0;
  663. X    save_point_size = point_size;
  664. X    
  665. X    (void)    signal (SIGINT, catch);        /*    for lpd quit */
  666. X
  667. X
  668. X#ifdef PSFFILTER
  669. X
  670. X    output_fp = stdout;
  671. X    input_fp  = stdin;
  672. X    if (header == 1)
  673. X        strcpy (fname, argv[optind]);
  674. X    else
  675. X        *fname = 0;    
  676. X
  677. X    if (fgets (line, LONG_STR, input_fp) == NULL)
  678. X        exit (0);
  679. X    if (tscan (line, "%!") >= 0  &&  print_postscript == 0)
  680. X    {    /*    already postscript  copy to output */
  681. X        if (fputs (line, output_fp) == EOF)
  682. X            output_trouble (2);
  683. X        while ((i = fgetc (input_fp)) != EOF)
  684. X        {    if (fputc (i, output_fp) == EOF)
  685. X                output_trouble (2);
  686. X        }
  687. X    }
  688. X    else
  689. X    {    /*    standard postscript conversion for file on stdin */
  690. Xbannerdone:
  691. X        if (font_number * 4 > font_count)
  692. X        {    fprintf (stderr,"Font number invalid....\n");
  693. X            usage ();
  694. X        }
  695. X
  696. X        if (book  ||  reverse_order)
  697. X        {    if ((output_fp = fopen (bookfile, "w")) == NULL)
  698. X            {    fprintf (stderr, "%s: cannot create work file\n", pgmname);
  699. X                exit (1);
  700. X            }
  701. X            if ((pg_loc = (long *) malloc (sizeof (long) * MAX_PAGES)) == NULL)
  702. X            {    fprintf (stderr, "%s: cannot allocate enough memory\n", pgmname);
  703. X                exit (1);
  704. X            }
  705. X            npg_loc = 0;
  706. X        }
  707. X
  708. X        for (i = 0;  i < NFONTS;  i++)
  709. X            fonts_used[i] = 0;
  710. X
  711. X        page_number = -1;
  712. X        line_number = 32000;
  713. X        default_point_size = point_size;
  714. X        default_font_number = font_number;
  715. X        bookwork = book  &&  landscape  &&  (max_frame == 2);
  716. X
  717. X        input_fp = stdin;
  718. X        get_time (now);        
  719. X        scale_factors ();
  720. X        prologue ();
  721. X        start_file ();
  722. X        process_file ();
  723. X        terminate_printer ();
  724. X        output_book (bookfile);
  725. X    }
  726. X
  727. X#else    /* not PSFFILTER */
  728. X
  729. X    /*    begin normal "psf" code */
  730. X
  731. X    if (font_number * 4 > font_count)
  732. X    {    fprintf (stderr,"Font number invalid....\n");
  733. X        usage ();
  734. X    }
  735. X
  736. X    if (book  ||  reverse_order)
  737. X    {    if ((output_fp = fopen (bookfile, "w")) == NULL)
  738. X        {    fprintf (stderr, "%s: cannot create work file\n", pgmname);
  739. X            exit (1);
  740. X        }
  741. X        if ((pg_loc = (long *) malloc (sizeof (long) * MAX_PAGES)) == NULL)
  742. X        {    fprintf (stderr, "%s: cannot allocate enough memory\n", pgmname);
  743. X            exit (1);
  744. X        }
  745. X        npg_loc = 0;
  746. X    }
  747. X    else    
  748. X    {    if (env_fname = getenv ("PSFLP"))
  749. X#if defined(MSDOS)  ||  defined (__MSDOS__)
  750. X        {    if ((output_fp = fopen (env_fname, "wt")) == NULL)
  751. X#else
  752. X        {    if ((output_fp = fopen (env_fname, "w")) == NULL)
  753. X#endif
  754. X            {    fprintf (stderr, "Cannot open output file %s\n", env_fname);
  755. X                exit (1);
  756. X            }
  757. X        }
  758. X        else
  759. X        {    output_fp = stdout;
  760. X        }
  761. X    }
  762. X
  763. X
  764. X    for (i = 0;  i < NFONTS;  i++)
  765. X        fonts_used[i] = 0;
  766. X
  767. X    page_number = -1;
  768. X    line_number = 32000;
  769. X    default_point_size = point_size;
  770. X    default_font_number = font_number;
  771. X    bookwork = book  &&  landscape  &&  (max_frame == 2);
  772. X    *fname = 0;    
  773. X
  774. X    get_time (now);        
  775. X    scale_factors ();
  776. X    prologue ();
  777. X    if (optind >=  argc)                        /*    process on stdin */
  778. X    {    input_fp = stdin;
  779. X        start_file ();
  780. X        process_file ();
  781. X    }
  782. X    else 
  783. X    {    for ( ;  optind < argc;  optind++)        /*    files from cmd line */
  784. X        {    strcpy (fname, argv[optind]);
  785. X            if ((input_fp = fopen (argv[optind], "r")) == NULL)
  786. X            {    fprintf (stderr, "Unknown file: %s\n", argv[optind]);
  787. X                continue;
  788. X            }
  789. X            start_file ();
  790. X            process_file ();
  791. X            fclose (input_fp);
  792. X        }
  793. X    }
  794. X    terminate_printer ();
  795. X
  796. X    output_book (bookfile);
  797. X    /*    end normal psf code */
  798. X
  799. X#endif    /* PSFFILTER */
  800. X
  801. X    exit (0);
  802. X}
  803. X
  804. X
  805. X/****************************************************************************
  806. X*    scale_factors ()                                                        *
  807. X*    Compute the x and y scale factors.                                        *
  808. X****************************************************************************/
  809. X
  810. X/*                    total paper size - unprintable size
  811. X    scale factor = --------------------------------------
  812. X                            print size
  813. X*/
  814. X
  815. Xvoid scale_factors ()
  816. X{    int    wide;                /*    width needed for char count            */
  817. X    int    high;                /*    points needed for line count        */
  818. X    int    n_lines;            /*    number of lines on a page            */
  819. X    int    i;
  820. X    double    char_width, scale;
  821. X    double    char_sf, line_sf;
  822. X    int        nominal_high, nominal_wide;
  823. X    int        on_portrait;
  824. X
  825. X    /*    use either the "portrait" or landscape width/height for basic scaling
  826. X    */
  827. X    switch (max_frame)
  828. X    {
  829. X    case 1:    on_portrait = 0;
  830. X            break;
  831. X    case 2: if (landscape)
  832. X                on_portrait = 1;
  833. X            else
  834. X                on_portrait = 0;
  835. X            break;
  836. X    case 4: if (landscape)
  837. X                on_portrait = 0;
  838. X            else
  839. X                on_portrait = 1;
  840. X    }
  841. X
  842. X    real_width = p->width;        /* for initial axis translate only    */
  843. X
  844. X    /*    if 4up in portrait or 2up, we want to shrink the image as
  845. X        though it were a proper 8.5x11 page.  thus do all calculations
  846. X        of line and column count as though it were a normal portrait page.
  847. X    */
  848. X    if (on_portrait)
  849. X    {    nominal_high = p->y_size;
  850. X        nominal_wide = p->x_size;
  851. X    }
  852. X    if (landscape)
  853. X    {
  854. X        i = p->height;      p->height    = p->width;        p->width      = i;
  855. X        i = p->left_marg;   p->left_marg = p->bot_marg;     p->bot_marg   = i;
  856. X        i = p->top_marg;    p->top_marg  = p->right_marg;   p->right_marg = i;
  857. X        i = p->lx;            p->lx        = p->ly;            p->ly          = i;
  858. X        i = p->ux;            p->ux        = p->uy;            p->uy          = i;
  859. X        i = p->x_size;        p->x_size    = p->y_size;        p->y_size      = i;
  860. X    }
  861. X    if (on_portrait == 0)
  862. X    {    nominal_high = p->y_size;
  863. X        nominal_wide = p->x_size;
  864. X    }
  865. X
  866. X    if (set_point_size)
  867. X    {    /*    if point size specified, ignore changes to rows and columns
  868. X            with -L, -l & -c.  They destroy character shape.
  869. X        */
  870. X        char_width = point_size / 12.0 * NOMINAL_CWIDE;
  871. X        n_chars = ceil ((double) nominal_wide / (double) char_width);
  872. X        n_lines = (double) nominal_high / (double) point_size;
  873. X        char_sf = 1.0;
  874. X        line_sf = 1.0;
  875. X
  876. X        if (set_total_count == 0  ||  lines_total > n_lines)
  877. X            lines_total = n_lines;
  878. X        if (set_line_count == 0  ||  lines_on_page > n_lines)
  879. X            lines_on_page = n_lines;
  880. X        if (lines_total < lines_on_page)
  881. X            lines_on_page = lines_total;
  882. X        if (header)                /* compress scale to allow headers */
  883. X        {    lines_on_page += 2;
  884. X            lines_total += 2;
  885. X            line_sf = (double) n_lines / (double) lines_total;
  886. X        }
  887. X    }
  888. X    else
  889. X    {    /*    determine independent scale factors to lines and columns
  890. X            based on user line and column count. This changes
  891. X            the character aspect ration - squashing it vertically
  892. X            and/or horizontally.
  893. X        */
  894. X        char_width = NOMINAL_CWIDE;
  895. X        n_chars = ceil ((double) nominal_wide / (double) char_width);
  896. X
  897. X        if (set_char_count)
  898. X            char_sf = (double) n_chars / (double) chars_on_line;
  899. X        else
  900. X        {    char_sf = 1.0;                /*    no change to char count */
  901. X            chars_on_line = n_chars;
  902. X        }
  903. X
  904. X        n_lines = (double) nominal_high / (double) point_size;
  905. X        if (set_total_count == 0)
  906. X            lines_total = n_lines;
  907. X        if (set_line_count == 0)
  908. X            lines_on_page = n_lines;
  909. X        if (lines_total < lines_on_page)
  910. X        {    if (set_total_count)
  911. X                lines_on_page = lines_total;
  912. X            else
  913. X                lines_total = lines_on_page;
  914. X        }
  915. X        if (header)                /* compress scale to allow headers */
  916. X        {    lines_on_page += 2;
  917. X            lines_total += 2;
  918. X        }
  919. X        line_sf = (double) n_lines / (double) lines_total;
  920. X    }
  921. X
  922. X    /*    theoretical points high and wide that we would "like" to
  923. X        have for our page - before scaling - including a 1/2 line
  924. X        for descenders for the last line.
  925. X    */
  926. X    high = ceil ((double) point_size * ((double) n_lines + 0.51));
  927. X    wide = ceil (n_chars * char_width);
  928. X
  929. X    x_user_offset = max (0, x_user_offset - p->left_marg);
  930. X    y_user_offset = max (0, y_user_offset - p->top_marg );
  931. X
  932. X    switch (max_frame)
  933. X    {
  934. X    case 1:
  935. X        scale_x = (double) (p->x_size) / (double) wide * char_sf;
  936. X        scale_y = (double) (p->y_size) / (double) high * line_sf;
  937. X        x_left_offset  = (int) ceil ((double) (p->left_marg + x_user_offset) / scale_x);
  938. X        y_top_offset   = (int) ceil ((double) (p->top_marg  + y_user_offset) / scale_y);
  939. X        dx_home[0] = 0;
  940. X        dy_home[0] = 0;
  941. X        p->height = ceil ((double) p->height / scale_y);
  942. X        p->width  = ceil ((double) p->width / scale_x);
  943. X        p->bot_marg = ceil ((double) p->bot_marg / scale_y);
  944. X        break;
  945. X
  946. X    case 2:
  947. X        scale_x = (double) (p->width - 2 * p->left_marg - 2 * p->right_marg)
  948. X                / (double) (2 * wide) * char_sf;
  949. X        scale_y = (double) (p->y_size) / (double) high * line_sf;
  950. X
  951. X        if (landscape == 0)
  952. X        {    scale_y /= 2.0;
  953. X            lines_total *= 2.0;
  954. X            lines_on_page *= 2.0;
  955. X        }
  956. X
  957. X        /*    point offsets for margins account for physical "forbidden" area */
  958. X
  959. X        x_left_offset  = (int) ceil ((double) p->left_marg / scale_x);
  960. X        y_top_offset   = (int) ceil ((double) p->top_marg / scale_y);
  961. X
  962. X        /*    page origin translation vectors    */
  963. X
  964. X        p->height = ceil ((double) p->height / scale_y);
  965. X        p->width  = ceil ((double) p->width  / (scale_x * 2.0));
  966. X        p->bot_marg = ceil ((double) p->bot_marg / scale_y);
  967. X        dx_home[0] = 0;
  968. X        dy_home[0] = 0;
  969. X        dx_home[1] = p->width;
  970. X        dy_home[1] = 0;
  971. X        break;
  972. X    
  973. X    case 4:
  974. X        scale_x = (double) (p->width - 2 * p->left_marg - 2 * p->right_marg)
  975. X                / (double) (2 * wide) * char_sf;
  976. X        scale_y = (double) (p->height - 2 * p->top_marg - 2 * p->bot_marg)
  977. X                / (double) (2 * high) * line_sf;
  978. X
  979. X        /*    point offsets for margins account for physical "forbidden" area */
  980. X
  981. X        x_left_offset = (int) ceil ((double) p->left_marg / scale_x);
  982. X        y_top_offset  = (int) ceil ((double) p->top_marg / scale_y);
  983. X
  984. X        /*    page origin tranlsation vectors    */
  985. X
  986. X        p->height = ceil ((double) p->height / (scale_y * 2.0));
  987. X        p->width  = ceil ((double) p->width  / (scale_x * 2.0));
  988. X        p->bot_marg = ceil ((double) p->bot_marg / scale_y);
  989. X        dx_home[0] = 0;
  990. X        dy_home[0] = p->height;
  991. X        dx_home[1] = p->width;
  992. X        dy_home[1] = 0;
  993. X        dx_home[2] = -p->width;
  994. X        dy_home[2] = -p->height;
  995. X        dx_home[3] = p->width;
  996. X        dy_home[3] = 0;
  997. X        break;
  998. X
  999. X    default: ;
  1000. X    }
  1001. X
  1002. X    if (max_frame > 1)
  1003. X    {    x_left_offset += x_user_offset;
  1004. X        y_top_offset  += y_user_offset;
  1005. X    }
  1006. X}
  1007. X
  1008. X
  1009. X/****************************************************************************
  1010. X*    prologue ()                                                                *
  1011. X*    generate the require postscript-conformant prologue                        *
  1012. X****************************************************************************/
  1013. X
  1014. Xvoid prologue ()
  1015. X{    char    *getlogin(), *me;
  1016. X    int        c;
  1017. X    FILE    *fp;
  1018. X
  1019. X    if (book  || reverse_order)
  1020. X        fprintf (output_fp, "%%Book file: psf-to-psfdoub\n");
  1021. X    else
  1022. X        fprintf (output_fp, "%%!PS-Adobe-\n");
  1023. X#if !defined(MSDOS)  && !defined(__MSDOS__)
  1024. X    me = getlogin();
  1025. X    if (me == NULL)                /* AT&T Unix 3.2 getlogin() is broken */
  1026. X#endif
  1027. X      me = "psf";                /* could use cuserid() instead        */
  1028. X    fprintf (output_fp, "%%%%Creator: %s\n", me);
  1029. X    fprintf (output_fp, "%%%%CreationDate: %s\n", now);
  1030. X    fprintf (output_fp, "%%%%DocumentFonts: (atend)\n");
  1031. X    fprintf (output_fp, "%%%%Pages: (atend)\n");
  1032. X    fprintf (output_fp, "%%%%EndComments\n");
  1033. X
  1034. X    /*    usage:         (text to underline) <pointsize> showuline
  1035. X        where:        <pointsize> is current text point size.
  1036. X
  1037. X        eg:            (text to underline) 12 showuline
  1038. X    */
  1039. X    fprintf (output_fp, "%s%s%s%s%s%s%s%s%s%s%s",
  1040. X            "/showuline {\n",
  1041. X            "    /CurPointSize exch def\n",
  1042. X            "    dup stringwidth pop\n",
  1043. X            "    gsave\n",
  1044. X            "    currentfont /FontInfo get dup\n",
  1045. X            "    /UnderlinePosition get CurPointSize mul 1000 div 0 exch rmoveto exch 0 rlineto\n",
  1046. X            "    /UnderlineThickness get CurPointSize mul 1000 div setlinewidth stroke\n",
  1047. X            "    grestore\n",
  1048. X            "    show\n",
  1049. X            "} def\n",
  1050. X            "/mv {moveto} def\n");
  1051. X
  1052. X    /*    add additional startup prologue code from psfprint.def
  1053. X        probably for non-English language support.
  1054. X    */
  1055. X    if (pdef)
  1056. X    {    while (fgets (line, LONG_STR, pdef))
  1057. X        {    if (fputs (line, output_fp) == EOF)
  1058. X                output_trouble (2);
  1059. X        }
  1060. X        fclose (pdef);
  1061. X        pdef = NULL;
  1062. X    }
  1063. X    
  1064. X    /*    copy a copyfile requested from psfprint.def */
  1065. X    
  1066. X    if (copyfile[0])
  1067. X    {    if (fp = fopen (copyfile, "r"))
  1068. X        {    while (1)
  1069. X            {    c = fgetc (fp);
  1070. X                if (feof (fp)  ||  ferror (fp))
  1071. X                    break;
  1072. X                if (fputc (c, fp) == EOF)
  1073. X                    output_trouble (2);
  1074. X            }
  1075. X            fclose (fp);
  1076. X        }
  1077. X    }
  1078. X        
  1079. X    fprintf (output_fp, "%%%%EndProlog\n");
  1080. X
  1081. X    if (set_paper_tray)
  1082. X        fprintf (output_fp, "%s\n", p->paper_tray);
  1083. X
  1084. X    if (order_command)
  1085. X        fprintf (output_fp, "%s\n", order_command);
  1086. X    else if (set_paper_bin)
  1087. X        fprintf (output_fp, "%s\n", slots[set_paper_bin - 1]);
  1088. X}
  1089. X
  1090. X/****************************************************************************
  1091. X*    showpage ()                                                                *
  1092. X*    Generate a real "showpage" if we have really finished generating a        *
  1093. X*    physical page.  If we are processing 2 or 4 up, then generate             *
  1094. X*    coordinate "translates" if we really haven't finished all possible        *
  1095. X*    page frames of the page.                                                *
  1096. X****************************************************************************/
  1097. X
  1098. Xvoid showpage (end_of_file)
  1099. Xint end_of_file;
  1100. X{    int        skipping;
  1101. X
  1102. X    line_number = 0;
  1103. X
  1104. X    if (max_frame > 1)
  1105. X        fprintf (output_fp, "grestore\n");
  1106. X
  1107. X    if (is_a_formfeed)            /*    don't skip if caused by form feed */
  1108. X        is_a_formfeed = 0;        /*    needed for lpr of= processing      */
  1109. X    else if (page_number > 0  &&  end_of_file == 0)
  1110. X    {    skipping = remove_between;
  1111. X        while (skipping--  &&  fgets (line, LONG_STR, input_fp))
  1112. X            ;
  1113. X        if (skipping >= 0)
  1114. X        {    end_of_file = 1;
  1115. X            if (bookwork == 0)                /* psfdoub will re-insert this */
  1116. X                fprintf (output_fp, "showpage pg restore\n");
  1117. X            frame = 0;
  1118. X            longjmp (eof_env, 1);
  1119. X        }
  1120. X    }
  1121. X
  1122. X    if (++frame >= max_frame  ||  end_of_file)
  1123. X    {    if (bookwork == 0)                    /* psfdoub will re-insert this */
  1124. X            fprintf (output_fp, "showpage pg restore\n");
  1125. X        frame = 0;
  1126. X    }
  1127. X    if (!end_of_file)
  1128. X        set_frame ();
  1129. X    
  1130. X}
  1131. X
  1132. X/****************************************************************************
  1133. X*    set_frame ()                                                            *
  1134. X*    Select the next logical frame in two-up or four-up mode.  If it is        *
  1135. X*    the first frame of a physical page, the generate the %%Page                *
  1136. X****************************************************************************/
  1137. X
  1138. Xvoid set_frame ()
  1139. X{
  1140. X    if (frame == 0  ||  bookwork)
  1141. X    {    if (book || reverse_order)        /*    mark byte position of %%Page: for psfdoub  */
  1142. X        {    pg_loc[npg_loc++] = ftell (output_fp);
  1143. X        }
  1144. X        fprintf (output_fp, "%%%%Page: ? %d\n", ++physical_page);
  1145. X        if (bookwork == 0)                    /* psfdoub will re-insert these */
  1146. X        {    fprintf (output_fp, "/pg save def\n");
  1147. X            if (landscape)
  1148. X                fprintf (output_fp, "90 rotate 0 %d translate\n", -real_width);
  1149. X            fprintf (output_fp, "%.5f %.5f scale\n", scale_x, scale_y);
  1150. X        }
  1151. X        findfont();
  1152. X    }
  1153. X
  1154. X    set_y_coord ();
  1155. X
  1156. X    if (max_frame > 1  &&  bookwork == 0)
  1157. X        fprintf (output_fp, "%d %d translate\n", dx_home[frame], dy_home[frame]);
  1158. X
  1159. X    if (frame == 0  &&  cross)
  1160. X        draw_cross();
  1161. X
  1162. X    if (max_frame > 1)
  1163. X    {    fprintf (output_fp, "gsave\n");
  1164. X        set_clip_path (0, 0, p->width, p->height);
  1165. X    }
  1166. X}
  1167. X
  1168. X
  1169. X/****************************************************************************
  1170. X*    set_y_coord                                                                *
  1171. X*    position next line to the top of a logical page.                        *
  1172. X*****************************************************************************/
  1173. X
  1174. Xvoid set_y_coord ()
  1175. X{
  1176. X    y_coord = p->height - y_top_offset - point_size;
  1177. X}
  1178. X
  1179. X/****************************************************************************
  1180. X*    put_top                                                                    *
  1181. X*    put a header line at the top of the page                                *
  1182. X*****************************************************************************/
  1183. X
  1184. Xvoid put_top ()
  1185. X{    int    save_attr, save_point, nc;
  1186. X    char    fmt[50], *hd;
  1187. X    
  1188. X    save_attr = print_attribute;
  1189. X    save_point = point_size;
  1190. X    print_attribute = BOLD;
  1191. X    point_size = save_point_size;
  1192. X
  1193. X    hd = (header == 1) ? fname : header_text;
  1194. X    nc = n_chars - 33;
  1195. X    if (nc < strlen (hd))
  1196. X        nc = strlen (hd) + 3;
  1197. X    sprintf (fmt, "(%%-%ds%%3d     %%s)show\n", nc);
  1198. X
  1199. X    findfont();
  1200. X    moveto (0, y_coord, 1);
  1201. X    fprintf (output_fp, fmt, hd, page_number + 1, now);
  1202. X    y_coord -= point_size * 2;
  1203. X    x_coord = 0;
  1204. X    print_attribute = save_attr;
  1205. X    point_size = save_point;
  1206. X    findfont();
  1207. X}
  1208. X
  1209. X/****************************************************************************
  1210. X*    process_file()                                                            *
  1211. X*    Read the file, look for escape sequences, put text in postscript form    *
  1212. X****************************************************************************/
  1213. X
  1214. Xvoid process_file ()
  1215. X{    int        char_type, char_count, i, set_page, esc_type;
  1216. X    char    *strchr ();
  1217. X    int        previous_attribute;
  1218. X    int        lcount = 0;
  1219. X    unsigned char    *xln;
  1220. X
  1221. X    set_page = 0;
  1222. X    i = remove_beginning;
  1223. X    while (i--  &&  fgets (line, LONG_STR, input_fp))
  1224. X        ;
  1225. X    if (i >= 0)
  1226. X    {    showpage (1);
  1227. X        return;
  1228. X    }
  1229. X
  1230. X    if (setjmp (eof_env))
  1231. X    {    return;
  1232. X    }
  1233. X
  1234. X#ifdef PSFFILTER
  1235. X    /*    psffilter already has a first line,  psf does not */
  1236. X    do
  1237. X#else
  1238. X    while (fgets (line, LONG_STR, input_fp) != NULL)
  1239. X#endif
  1240. X    {
  1241. X        if (*line == CTLD_EOJ)        /* printing postscript code: ^D at end    */
  1242. X            break;                    /* assume it is end of file also        */
  1243. X
  1244. X        if (lcount++ == 0)
  1245. X        {    if ((i = tscan (line, "ta=")) >= 0)
  1246. X            {    tab_size = atoi (line + i + 3);
  1247. X            }
  1248. X        }
  1249. X
  1250. X        if (need_xlate)                /*    translate character set? */
  1251. X        {    xln = (unsigned char *) line;
  1252. X            while (*xln)
  1253. X            {    i = *xln;
  1254. X                *xln++ = xlate[i];
  1255. X            }
  1256. X        }
  1257. X
  1258. X        if ((c = strchr (line, '\f')) != NULL)
  1259. X        {    if (c == line)
  1260. X            {    line_number = 32000;
  1261. X                c = line + 1;
  1262. X            }
  1263. X            else
  1264. X            {    *c = 0;
  1265. X                set_page = 1;
  1266. X                c = line;
  1267. X            }
  1268. X            is_a_formfeed = 1;
  1269. X        }
  1270. X        else
  1271. X            c = line;
  1272. X
  1273. X        if (line_number >= lines_on_page * 10)
  1274. X        {    page_number++;
  1275. X            showpage (0);
  1276. X            line_number = 10;
  1277. X            if (header)
  1278. X            {    put_top();
  1279. X                line_number += 20;
  1280. X            }
  1281. X        }
  1282. X        else
  1283. X            line_number += 10;
  1284. X
  1285. X        char_type = char_count = 0;
  1286. X
  1287. X        /*    for empty lines, don't generate a real moveto - but to call
  1288. X            to ensure that check for page overflow is done.
  1289. X        */
  1290. X        if (*c == '\n')
  1291. X            moveto (x_coord, y_coord, 0);        /*    don't gen moveto    */
  1292. X        else
  1293. X            moveto (x_coord, y_coord, 1);        /*    do gen moveto        */
  1294. X
  1295. X        while (*c  && *c != '\n')
  1296. X        {    if (char_type == 0)
  1297. X            {    if (fputc ('(', output_fp) == EOF)
  1298. X                    output_trouble (2);
  1299. X            }
  1300. X            switch ((int) *c)
  1301. X            {
  1302. X            case ESCAPE:
  1303. X                previous_attribute = print_attribute;
  1304. X                esc_type = *(++c);
  1305. X                if (escape_sequence (esc_type) == 0)
  1306. X                {    switch (esc_type)
  1307. X                    {
  1308. X                    case 'u':
  1309. X                        SHOWU (output_fp, point_size);
  1310. X                        break;
  1311. X
  1312. X                    default:
  1313. X                        if (char_type  &&  (previous_attribute & UNDERLINE))
  1314. X                            SHOWU (output_fp, point_size);
  1315. X                        else
  1316. X                        {    if (fputs (")show\n", output_fp) == EOF)
  1317. X                                output_trouble (2);
  1318. X                        }
  1319. X                        if (esc_type == '+'  ||  esc_type == '-')
  1320. X                        {    /*    check for +/- 1/2 line feed        */
  1321. X                            if (esc_type == '+')
  1322. X                                y_coord -= point_size / 2;
  1323. X                            else
  1324. X                                y_coord += point_size / 2;
  1325. X                            moveto (x_coord, y_coord, 1);
  1326. X                            char_type = -1;
  1327. X                            c++;
  1328. X                            if (*c != '\n')
  1329. X                            {    if (fputc ('(', output_fp) == EOF)
  1330. X                                    output_trouble (2);
  1331. X                            }
  1332. X                            continue;
  1333. X                        }
  1334. X                        else
  1335. X                            findfont ();
  1336. X                    }
  1337. X                    char_type = 0;
  1338. X                }
  1339. X                break;
  1340. X
  1341. X            default:
  1342. X                if (*c == '\t')
  1343. X                {    fputc (' ', output_fp);
  1344. X                    while (++char_count % tab_size)
  1345. X                    {    if (fputc (' ', output_fp) == EOF)
  1346. X                            output_trouble (2);
  1347. X                    }
  1348. X                }
  1349. X                else
  1350. X                {    if (strchr ("\r\b\\()", *c) != NULL)
  1351. X                    if (fputc ('\\', output_fp) == EOF)
  1352. X                        output_trouble (2);
  1353. X                    if (fputc (*c, output_fp) == EOF)
  1354. X                        output_trouble (2);
  1355. X                    char_count++;
  1356. X                }
  1357. X                char_type = 1;
  1358. X                break;
  1359. X            }
  1360. X            c++;
  1361. X        }
  1362. X        if (char_type == 1)
  1363. X        {    if (print_attribute & UNDERLINE)
  1364. X                SHOWU (output_fp, point_size);
  1365. X            else
  1366. X            {    if (fputs (")show\n", output_fp) == EOF)
  1367. X                    output_trouble (2);
  1368. X            }
  1369. X        }
  1370. X
  1371. X        y_coord -= point_size;
  1372. X        x_coord = 0;
  1373. X        if (set_page)
  1374. X        {    line_number = 32000;
  1375. X            set_page = 0;
  1376. X        }
  1377. X#ifdef PSFFILTER
  1378. X    } while (fgets (line, LONG_STR, input_fp) != NULL);
  1379. X#else
  1380. X    }
  1381. X#endif
  1382. X    if (end_of_file == 0)
  1383. X        showpage (1);
  1384. X}
  1385. X
  1386. X/****************************************************************************
  1387. X*    escape_sequence ()                                                        *
  1388. X*    If an escape sequence (esc,char) is found, mark which type of font        *
  1389. X****************************************************************************/
  1390. X
  1391. Xint escape_sequence (which)
  1392. Xint    which;
  1393. X{    char    s[10];
  1394. X
  1395. X    switch (which)
  1396. X    {
  1397. X    case 'I':
  1398. X        print_attribute |= ITALICS;
  1399. X        break;
  1400. X
  1401. X    case 'i':
  1402. X        print_attribute &= ~ITALICS;
  1403. X        break;
  1404. X
  1405. X    case 'B':
  1406. X        print_attribute |= BOLD;
  1407. X        break;
  1408. X
  1409. X    case 'b':
  1410. X        print_attribute &= ~BOLD;
  1411. X        break;
  1412. X
  1413. X    case 'U':
  1414. X        print_attribute |= UNDERLINE;
  1415. X        break;
  1416. X
  1417. X    case 'u':
  1418. X        print_attribute &= ~UNDERLINE;
  1419. X        break;
  1420. X
  1421. X    case 'F':
  1422. X        s[0] = *(++c);
  1423. X        s[1] = '\0';
  1424. X        font_number = xtoi ((int) *s);        
  1425. X        if (font_number > (font_count / 4))
  1426. X            font_number = (font_count / 4) - 1;
  1427. X        break;
  1428. X
  1429. X    case 'f':
  1430. X        font_number = default_font_number;
  1431. X        break;
  1432. X
  1433. X    case 'P':
  1434. X        s[0] = *(++c);
  1435. X        s[1] = *(++c);
  1436. X        s[2] = '\0';
  1437. X        point_size = atoi (s);
  1438. X        break;
  1439. X
  1440. X    case 'p':
  1441. X        point_size = default_point_size;
  1442. X        break;
  1443. X
  1444. X    case '+':
  1445. X    case '-':
  1446. X        break;
  1447. X
  1448. X    default:
  1449. X        return (-1);
  1450. X        ;
  1451. X    }
  1452. X    return (0);
  1453. X}
  1454. X
  1455. X/****************************************************************************
  1456. X*    moveto ()                                                                *
  1457. X*    Generate a postscript     x y moveto    statememt                        *
  1458. X****************************************************************************/
  1459. X
  1460. Xvoid moveto (x, y, do_move)
  1461. Xint    x;
  1462. Xint    y;
  1463. Xint do_move;            /*    1 = gen moveto     0 = dont gen moveto    */
  1464. X{
  1465. X    /*    ensure that the current line can fit on the page - including the
  1466. X        1/4 line needed for the decenders
  1467. X    */
  1468. X
  1469. X    if (line_number > lines_on_page * 10  ||  y < (p->bot_marg + point_size / 3))
  1470. X    {    if (line_number < lines_on_page * 10)
  1471. X            page_number++;
  1472. X        showpage (0);
  1473. X        if (header)
  1474. X        {    put_top();
  1475. X            line_number += 20;
  1476. X        }
  1477. X        y = y_coord;
  1478. X        x = x_coord;
  1479. X    }
  1480. X
  1481. X    if (do_move)
  1482. X        fprintf (output_fp, "%d %d mv ", x + x_left_offset, y);
  1483. X}
  1484. X
  1485. X/****************************************************************************
  1486. X*    findfont ()                                                                *
  1487. X*    generate a findfont statement                                            *
  1488. X****************************************************************************/
  1489. X
  1490. Xvoid findfont ()
  1491. X{    int    this;
  1492. X
  1493. X    /*    remove reference to UNDERLINE.  Underline is not a font.    */
  1494. X
  1495. X    this = (font_number * 4) + (print_attribute & 0x03);
  1496. X    fonts_used[this] = 1;
  1497. X    fprintf (output_fp, "/%s findfont %d scalefont setfont\n", fonts[this], point_size);
  1498. X}
  1499. X
  1500. X/****************************************************************************
  1501. X*    start_file ()                                                            *
  1502. X*    Generate things that are appropriate for beginning of file processing    *
  1503. X****************************************************************************/
  1504. X
  1505. Xvoid start_file ()
  1506. X{
  1507. X    end_of_file = 0;
  1508. X    line_number = 0;
  1509. X    print_attribute = 0;
  1510. X    page_number = 0;
  1511. X    frame = 0;
  1512. X    set_frame ();
  1513. X    if (header)
  1514. X    {    put_top();
  1515. X        line_number += 20;
  1516. X    }
  1517. X}
  1518. X
  1519. X
  1520. X/****************************************************************************
  1521. X*    terminate_printer ()                                                    *
  1522. X*    Generate things that are appropriate wrap-up after all files printed    *
  1523. X*    For double sided printing (book == 1), generate byte offset info.        *
  1524. X****************************************************************************/
  1525. X
  1526. Xvoid terminate_printer ()
  1527. X{    int    i, used;
  1528. X    long    psfptr;
  1529. X
  1530. X    if (book || reverse_order)
  1531. X    {    pg_loc[npg_loc++] = ftell (output_fp);
  1532. X    }
  1533. X    fprintf (output_fp, "%%%%Trailer\n");
  1534. X    for (used = i = 0;  i < font_count;  i++)
  1535. X    {    if (fonts_used[i])
  1536. X        {    used = 1;
  1537. X            break;
  1538. X        }
  1539. X    }
  1540. X    if (used)
  1541. X    {    fprintf (output_fp, "%%%%DocumentFonts:");
  1542. X        for (i = 0;  i < font_count;  i ++)
  1543. X        {    if (fonts_used[i])
  1544. X                fprintf (output_fp, " %s", fonts[i]);
  1545. X        }
  1546. X        fprintf (output_fp, "\n");
  1547. X    }
  1548. X
  1549. X    fprintf (output_fp, "%%%%Pages: %d\n", physical_page);
  1550. X
  1551. X    if (book || reverse_order)            /*    print statistics for psfdoub  */
  1552. X    {    psfptr = ftell (output_fp);
  1553. X        fprintf (output_fp, "%%PsfScale: %.5f %.5f scale\n", scale_x, scale_y);
  1554. X        fprintf (output_fp, "%%PsfMargin: %d %d %d %d %d\n", 
  1555. X                        max_frame, landscape, real_width, p->height, p->width);
  1556. X        for (i = 0;  i < 4;  i++)
  1557. X            fprintf (output_fp, "%%PsfHome: %d %d %d\n",  i, dx_home[i], dy_home[i]);
  1558. X        for (i = 0;  i < npg_loc-1;  i++)
  1559. X            fprintf (output_fp, "%%PsfPg: %d %d\n",  i, pg_loc[i]);
  1560. X        fprintf (output_fp, "%%PsfPg: 9999 %d\n", pg_loc[npg_loc-1]);
  1561. X        fprintf (output_fp, "%%PsfPtr: %d\n", psfptr);
  1562. X    }
  1563. X    fprintf (output_fp, "%c", CTLD_EOJ);        /* CTL/D = end job */
  1564. X}
  1565. X
  1566. X/****************************************************************************
  1567. X*    draw_cross ()                                                            *
  1568. X*    Draw horizontal and vertical separation lines between pages 2/4-up        *
  1569. X****************************************************************************/
  1570. X
  1571. Xvoid draw_cross ()
  1572. X{    int     p_w, p_h;
  1573. X
  1574. X    if (max_frame > 1)
  1575. X    {    p_w = p->width;
  1576. X        p_h = p->height;
  1577. X        if (max_frame == 4)
  1578. X        {    set_clip_path (0, -p_h, p_w * 2, p_h);
  1579. X            fprintf (output_fp,"gsave %d %d moveto\n", p_w, p_h);
  1580. X            fprintf (output_fp,"%d %d lineto\n", p_w, -p_h);
  1581. X            fprintf (output_fp,"%d %d moveto\n", 0, 0);
  1582. X            fprintf (output_fp,"%d %d lineto\n", p_w * 2, 0);
  1583. X            fprintf (output_fp,"%s\n", "stroke grestore");
  1584. X        }
  1585. X        else
  1586. X        {    set_clip_path (0, 0, p_w * 2+ 1, p_h + 1);
  1587. X            fprintf (output_fp,"gsave %d %d moveto\n", p_w, p_h);
  1588. X            fprintf (output_fp,"%d %d lineto\n", p_w, 0);
  1589. X            fprintf (output_fp,"%s\n", "stroke grestore");
  1590. X        }
  1591. X    }
  1592. X}
  1593. X
  1594. X/****************************************************************************
  1595. X*    set_clip_path                                                            *
  1596. X****************************************************************************/
  1597. X
  1598. Xvoid set_clip_path (x1, y1, x2, y2)
  1599. Xint    x1, y1, x2, y2;
  1600. X{
  1601. X    x1--; y1--; x2++; y2++;
  1602. X
  1603. X    fprintf (output_fp, "newpath\n");
  1604. X    fprintf (output_fp,"%d %d moveto\n", x1, y1);
  1605. X    fprintf (output_fp,"%d %d lineto\n", x1, y2);
  1606. X    fprintf (output_fp,"%d %d lineto\n", x2, y2);
  1607. X    fprintf (output_fp,"%d %d lineto\n", x2, y1);
  1608. X    fprintf (output_fp,"%s\n", "closepath clip");
  1609. X}
  1610. X
  1611. X/****************************************************************************
  1612. X*    output_book ()                                                            *
  1613. X*    Send file "double sided print" mode.  Used to make a "book".            *
  1614. X****************************************************************************/
  1615. X
  1616. Xvoid output_book (bookfile)
  1617. Xchar    *bookfile;
  1618. X{    char    opts[50];
  1619. X
  1620. X    if (book == 0  &&  reverse_order == 0)
  1621. X        return;
  1622. X
  1623. X#ifdef HOPPER
  1624. X
  1625. X    if (nslots > 1  ||  reverse_order)
  1626. X    {    if (output_fp != stdout)
  1627. X        {    fflush (output_fp);
  1628. X            fclose (output_fp);
  1629. X
  1630. X            sprintf (opts, "%s %s", reverse_requested ? "-v" : "",
  1631. X                                     book ? "-3" : "");
  1632. X
  1633. X#if defined(MSDOS)  ||  defined(__MSDOS__)
  1634. X            sprintf (line, "%s %s -u %s %s", PSFDOUB, opts, defref, bookfile);
  1635. X#else
  1636. X            sprintf (line, "%s/%s %s -u %s %s", BINDIR, PSFDOUB, opts, defref, bookfile);
  1637. X#endif
  1638. X            system (line);
  1639. X            unlink (bookfile);
  1640. X        }
  1641. X    }
  1642. X
  1643. X
  1644. X#else    /*    not HOPPER    */
  1645. X    if (reverse_order)
  1646. X    {    if (output_fp != stdout)
  1647. X        {    fflush (output_fp);
  1648. X            fclose (output_fp);
  1649. X        
  1650. X            sprintf (opts, "%s", reverse_requested ? "-v" : "");
  1651. X
  1652. X#if defined(MSDOS)  ||  defined(__MSDOS__)
  1653. X            sprintf (line, "%s %s -u %s %s", PSFDOUB, opts, defref, bookfile);
  1654. X#else
  1655. X            sprintf (line, "%s/%s %s -u %s %s", BINDIR, PSFDOUB, opts, defref, bookfile);
  1656. X#endif
  1657. X            system (line);
  1658. X            unlink (bookfile);
  1659. X        }
  1660. X    }    
  1661. X
  1662. X
  1663. X#endif    /* HOPPER */
  1664. X}
  1665. X
  1666. X
  1667. X/************************************************************************
  1668. X*        tscan (s,t)                                                        *        
  1669. X*    look for string t in s. return -1 if t does not exits in s else        *
  1670. X*    return array position of first character match                        *
  1671. X************************************************************************/
  1672. X
  1673. Xint tscan (s, t)
  1674. Xchar     s[], t[];
  1675. X{
  1676. X    int    i, j, k;
  1677. X    for (i = 0;  s[i] != '\0';  i++)
  1678. X    {    for (j = i, k=0;  t[k] != '\0'  &&  s[j] == t[k];  j++, k++)
  1679. X            ;
  1680. X        if (t[k] == '\0')
  1681. X            return (i);
  1682. X    }
  1683. X    return (-1);
  1684. X}
  1685. X
  1686. Xvoid get_time (t)                /*    get current time of */
  1687. Xchar    *t;
  1688. X{
  1689. X    long    n_time, time ();
  1690. X    char    *x_time, *cc, *strchr();
  1691. X
  1692. X    n_time = time (0);            /* get time */
  1693. X    x_time = ctime (&n_time);    /* convert ascii */
  1694. X    if ((cc = strchr (x_time, '\n')) != NULL)
  1695. X        *cc = '\0';
  1696. X    strcpy (t, x_time);
  1697. X}
  1698. X
  1699. Xint compare (a,b)                /*    case insensitive compare */
  1700. Xchar    *a, *b;
  1701. X{    int    aa, bb;
  1702. X
  1703. X    while (*a)
  1704. X    {    aa = *a++;
  1705. X        bb = *b++;
  1706. X        if (UCCHAR (aa)  !=  UCCHAR (bb))
  1707. X            return (UCCHAR(aa) - UCCHAR(bb));
  1708. X    }
  1709. X    return (UCCHAR (*a) - UCCHAR (*b));
  1710. X}
  1711. X
  1712. Xint partial_compare (a,b)            /*    case insensitive compare */
  1713. Xchar    *a, *b;                        /*    if all parts of 'a' are successful */
  1714. X{    int    aa, bb;
  1715. X
  1716. X    while (*a)
  1717. X    {    aa = *a++;
  1718. X        bb = *b++;
  1719. X        if (UCCHAR (aa)  !=  UCCHAR (bb))
  1720. X            return (UCCHAR(aa) - UCCHAR(bb));
  1721. X    }
  1722. X    return (0);
  1723. X}
  1724. X
  1725. Xint comparen (a,b, n)            /* case insensitive compare with count limit */
  1726. Xchar    *a, *b;
  1727. Xint        n;
  1728. X{    int    aa, bb;
  1729. X
  1730. X    while (*a &&  n--)
  1731. X    {    aa = *a++;
  1732. X        bb = *b++;
  1733. X        if (UCCHAR (aa)  !=  UCCHAR (bb))
  1734. X            return (UCCHAR(aa) - UCCHAR(bb));
  1735. X    }
  1736. X    if (n <= 0)
  1737. X        return (0);
  1738. X    return (UCCHAR (*a) - UCCHAR (*b));
  1739. X}
  1740. X
  1741. Xint endcompare (a,b)            /* compare end of a with b */
  1742. Xchar    *a, *b;
  1743. X{
  1744. X    int    na, nb;
  1745. X    
  1746. X    na = strlen (a);
  1747. X    nb = strlen (b);
  1748. X    if (na > nb)
  1749. X        a += na - nb;
  1750. X    return (strcmp (a,b));
  1751. X}
  1752. X
  1753. X
  1754. Xvoid trim (s)                    /*    trim trailing blanks  and \n */
  1755. Xchar    *s;
  1756. X{    int many;
  1757. X
  1758. X    for (many = strlen (s) - 1;  many >= 0;  many--)
  1759. X    {    if (isgraph (s[many]))
  1760. X            break;
  1761. X        else
  1762. X            s[many] = '\0';
  1763. X    }
  1764. X}
  1765. X
  1766. Xvoid bad_file()
  1767. X{
  1768. X    fprintf (stderr, "Bad %s file\n", defref);
  1769. X    exit (1);
  1770. X}
  1771. X
  1772. Xint xtoi (c)                    /*    hex character to integer     */
  1773. Xint c;                            /*    any letter is a 'hex' digit */
  1774. X{
  1775. X    char xc[2];
  1776. X    int     rv;
  1777. X    
  1778. X    if (isupper (c))
  1779. X        xc[0] = tolower (c);
  1780. X    else
  1781. X        xc[0] = c;
  1782. X    xc[1] = '\0';
  1783. X    
  1784. X    rv = tscan (ascii_hex, xc);
  1785. X    if (rv >= 0)
  1786. X        return (rv);
  1787. X    return (0);
  1788. X}
  1789. X
  1790. X
  1791. X/********************************************************
  1792. X*    catch ()                                            *
  1793. X*    Catch SIGINT from lpd                                *
  1794. X********************************************************/
  1795. X
  1796. Xvoid catch (signo)
  1797. Xint    signo;
  1798. X{
  1799. X        fprintf (output_fp, "%c", CTLD_EOJ);
  1800. X        exit (0);
  1801. X}
  1802. X
  1803. Xvoid output_trouble (rc)
  1804. Xint    rc;
  1805. X{
  1806. X#ifndef PSFFILTER
  1807. X    fprintf (stderr, "Cannot write to output file\n");
  1808. X#endif
  1809. X    exit (rc);
  1810. X}
  1811. X/************************************************************************
  1812. X*    replacement_fonts()                                                    *
  1813. X*    get language-specific fonts and translation vectors.                *
  1814. X*    Reads only the %%PsfStart -to- %%PsfEnd code.  The file is is left    *
  1815. X*    positioned at the first postscript code that prologue() will copy    *
  1816. X*    to the output.                                                        *
  1817. X************************************************************************/
  1818. X
  1819. Xvoid replacement_fonts ()
  1820. X{    int        found, i, fn, xold, xnew;
  1821. X    char    line[201];
  1822. X    char    *ln, *x, *fname;
  1823. X
  1824. X    if (pdef == NULL)
  1825. X        return;
  1826. X    found = 0;
  1827. X    while (fgets (line, 200, pdef))        /*    skip printer name     */
  1828. X    {    if (strncmp (line, "%%PsfStart", 10) == 0)
  1829. X        {    found = 1;
  1830. X            break;
  1831. X        }
  1832. X    }
  1833. X    if (found)
  1834. X    {    while (fgets (line, 200, pdef))            /*    read fonts, translate */
  1835. X        {    if (strncmp (line, "%%PsfEnd", 8) == 0)
  1836. X                break;
  1837. X            if (strncmp (line, "%%font",  6) == 0)
  1838. X            {    fn = xtoi (line[6]) * 4;
  1839. X                if (fn >= font_count)
  1840. X                    font_count = fn + 4;
  1841. X                trim (line);
  1842. X                ln = malloc (strlen (line) - 6);
  1843. X                strcpy (ln, line + 7);
  1844. X                fonts_have[fn] = 1;
  1845. X                fonts[fn++] = strtok (ln, " \t");
  1846. X                for (i = 1;  i < 4;  i++)
  1847. X                {    fonts_have[fn] = 1;
  1848. X                    fonts[fn++] = strtok (NULL, " \t");
  1849. X                }
  1850. X            }
  1851. X            else if (strncmp (line, "%%translate",  11) == 0)
  1852. X            {    x = strtok (line + 11, " \t");
  1853. X                do
  1854. X                {    xold = otoi (x) % 256;
  1855. X                    xnew = otoi (x+4) % 256;
  1856. X                    xlate[xold] = xnew;
  1857. X                } while (x = strtok (NULL, " \t"));
  1858. X                need_xlate = 1;
  1859. X            }
  1860. X            else if (strncmp (line, "%%copy", 6) == 0)
  1861. X            {    fname = strtok (line + 6, " \t");
  1862. X                if (fname)
  1863. X                    strcpy (copyfile, fname);
  1864. X            }
  1865. X        }
  1866. X    }
  1867. X    else
  1868. X    {    fclose (pdef);
  1869. X        pdef = NULL;
  1870. X    }
  1871. X    return;
  1872. X}
  1873. X
  1874. X/****************************************************************************
  1875. X*    octal to integer                                                        *
  1876. X****************************************************************************/
  1877. Xint    otoi (s)
  1878. Xchar    *s;
  1879. X{
  1880. X    int        v, p, quit;
  1881. X
  1882. X    v = 0;
  1883. X    while (*s == ' ')
  1884. X        s++;
  1885. X    quit = 0;
  1886. X    while (*s)
  1887. X    {    switch (*s)
  1888. X        {
  1889. X        case '0':    p = 0;  break;
  1890. X        case '1':    p = 1;  break;
  1891. X        case '2':    p = 2;  break;
  1892. X        case '3':    p = 3;  break;
  1893. X        case '4':    p = 4;  break;
  1894. X        case '5':    p = 5;  break;
  1895. X        case '6':    p = 6;  break;
  1896. X        case '7':    p = 7;  break;
  1897. X        default:    quit = 1;
  1898. X        }
  1899. X        if (quit)
  1900. X            break;
  1901. X        v = (v << 3) + p;
  1902. X        s++;
  1903. X    }
  1904. X    return (v);
  1905. X}
  1906. X
  1907. X/****************************************************************************
  1908. X*    usage ()                                                                *
  1909. X****************************************************************************/
  1910. X
  1911. X#ifdef PSFFILTER
  1912. X
  1913. Xvoid usage ()
  1914. X{    exit (1);
  1915. X}
  1916. Xvoid size_display ()
  1917. X{    exit (1);
  1918. X}
  1919. X
  1920. X#else    /* not PSFFILTER */
  1921. X
  1922. Xstatic char *usage_text[] =
  1923. X{
  1924. X    "Usage: %s [-1|2|4] [-b n] [-c n] [-d] [-f n] [-g type ] [-h]\n",
  1925. X    "           [-H text] [-i n] [-l n] [-m n] [-n] [-p n] [-R n]",
  1926. X    "           [-r n] [-s] [-t n] [-u fil] [-w] [-x] file ...",
  1927. X    "where:",
  1928. X    "   -1|2|4  print 1,2,4 up (default=1)",
  1929. X    "   -b n    paper bin n",
  1930. X    "   -c n    print columns",
  1931. X    "   -d      double sided",
  1932. X    "   -f n    font number (def=0:Courier)",
  1933. X    "   -g type letter legal a4 b5",
  1934. X    "   -h      file name header",
  1935. X    "   -H text text header",
  1936. X    "   -i n    indent left margin points",
  1937. X    "   -l n    print lines per page",
  1938. X    "   -L n    lines per page",
  1939. X    "   -m n    top margin points",
  1940. X    "   -n      portrait (narrow) format",
  1941. X    "   -p n    point size n",
  1942. X    "   -R n    remove lines from beginning",
  1943. X    "   -r n    remove lines between pages",
  1944. X    "   -s      show page stats",
  1945. X    "   -t n    tabs to n (default=8)",
  1946. X    "   -u fil  use this file as psfprint.def",
  1947. X    "   -v      reverse page order",
  1948. X    "   -w      landscape (wide) format",
  1949. X    "   -x      draw cross (2/4-up page)",
  1950. X    "   file..  name of files (or stdin)",
  1951. X    "   output: stdout",
  1952. X    ""
  1953. X} ;
  1954. X
  1955. X#define TOPCOUNT 4
  1956. X
  1957. Xvoid usage ()
  1958. X{    int        i, many, n, ff;
  1959. X
  1960. X    fprintf (stderr, usage_text[0], pgmname);
  1961. X    for (i = 1;  i < TOPCOUNT; i++)
  1962. X        fprintf (stderr, "%s\n", usage_text[i]);
  1963. X
  1964. X    many = sizeof (usage_text)/sizeof (char *) - TOPCOUNT;
  1965. X    
  1966. X    for (i = 0;  i < many/2;  i++)
  1967. X        fprintf (stderr, "%-38s %-38s\n", usage_text[i+TOPCOUNT], usage_text[i+many/2+TOPCOUNT]);
  1968. X
  1969. X    fprintf (stderr,"Fonts selection with -f n (number or name)\n");
  1970. X    many = ff = 0;
  1971. X    for (i = 0;  i < font_count/4;  i++)
  1972. X    {    if (fonts_have[i*4])
  1973. X        {    fprintf (stderr, " %c %-22s", ascii_hex[i], fonts[i*4]);
  1974. X            many++;
  1975. X            if ((ff = many % 3)  == 0)
  1976. X                fprintf (stderr, "\n");
  1977. X        }
  1978. X    }
  1979. X    if (ff)
  1980. X        fprintf (stderr, "\n");
  1981. X
  1982. X    fprintf (stderr, "Paper type/size selection with -g type\n");
  1983. X    many = 0;
  1984. X    for (i = 0;  page_types[i].paper_name[0] != '\0';  i++)
  1985. X    {    n = strlen (page_types[i].paper_name);
  1986. X        if (many + n > 75)
  1987. X        {    many = 0;
  1988. X            fprintf (stderr,"\n");
  1989. X            ff = 0;
  1990. X        }
  1991. X        else ff = 1;
  1992. X        many += n + 3;
  1993. X        fprintf (stderr,"   %s", page_types[i].paper_name);
  1994. X    }
  1995. X    if (ff)
  1996. X        fprintf (stderr, "\n");
  1997. X    exit (1);
  1998. X}
  1999. X
  2000. X/************************************************************************
  2001. X*    size_display ()                                                        *
  2002. X*    print a table of point size, page size, line count, column count    *
  2003. X************************************************************************/
  2004. X
  2005. Xvoid size_display ()
  2006. X{
  2007. X    int    point_size, ps, nominal_high, nominal_wide, i;
  2008. X    int    n_chars, n_lines;
  2009. X    double    char_width;
  2010. X    char    *which;
  2011. X    
  2012. X    fprintf (stderr, "%22s", "point size: ");
  2013. X    for (point_size = 6;  point_size < 17;  point_size += 2)
  2014. X        fprintf (stderr, " %5d   ", point_size);
  2015. X    fprintf (stderr, "\n%-22s", " ");
  2016. X    for (point_size = 6;  point_size < 17;  point_size += 2)
  2017. X        fprintf (stderr, "  lin col");
  2018. X    fprintf (stderr, "\n%-22s", "---- Page Layout ----");
  2019. X    for (point_size = 6;  point_size < 17;  point_size += 2)
  2020. X        fprintf (stderr, "  --- ---");
  2021. X    fprintf (stderr, "\n");
  2022. X    for (ps = 0;  page_types[ps].paper_name[0];  ps++)
  2023. X    {    for (i = 0;  i < 2;  i++)
  2024. X        {    if (i == 0)
  2025. X            {    nominal_high = page_types[ps].y_size;
  2026. X                nominal_wide = page_types[ps].x_size;
  2027. X                which = "portrait";
  2028. X            }
  2029. X            else
  2030. X            {    nominal_high = page_types[ps].x_size;
  2031. X                nominal_wide = page_types[ps].y_size;
  2032. X                which = "landscape";
  2033. X            }
  2034. X            fprintf (stderr, "%10.10s %9s: ", page_types[ps].paper_name, which);
  2035. X            for (point_size = 6;  point_size < 17;  point_size += 2)
  2036. X            {    char_width = point_size / 12.0 * NOMINAL_CWIDE;
  2037. X                n_chars = ceil ((double) nominal_wide / (double) char_width);
  2038. X                n_lines = (double) nominal_high / (double) point_size;
  2039. X                fprintf (stderr, " %4d%4d", n_lines, n_chars);
  2040. X            }
  2041. X            fprintf (stderr, "\n");
  2042. X        }
  2043. X    }
  2044. X    exit (1);
  2045. X}
  2046. X#endif /* PSFFILTER */
  2047. END_OF_FILE
  2048. if test 52453 -ne `wc -c <'psf.c'`; then
  2049.     echo shar: \"'psf.c'\" unpacked with wrong size!
  2050. fi
  2051. # end of 'psf.c'
  2052. fi
  2053. echo shar: End of archive 9 \(of 9\).
  2054. cp /dev/null ark9isdone
  2055. MISSING=""
  2056. for I in 1 2 3 4 5 6 7 8 9 ; do
  2057.     if test ! -f ark${I}isdone ; then
  2058.     MISSING="${MISSING} ${I}"
  2059.     fi
  2060. done
  2061. if test "${MISSING}" = "" ; then
  2062.     echo You have unpacked all 9 archives.
  2063.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  2064. else
  2065.     echo You still need to unpack the following archives:
  2066.     echo "        " ${MISSING}
  2067. fi
  2068. ##  End of shell archive.
  2069. exit 0
  2070.  
  2071. exit 0 # Just in case...
  2072.